﻿#include "ASM330.h"
#include "spi.h"
#include "delay.h"
#include "usart.h"
#include "sys.h"
#include "string.h"
#include "time.h"
#include "BG35.h"
#include "stm32f10x_usart.h"

typedef struct
{
  char instruction[600];
  void (*handleOk)();
  void (*handleError)();
  void (*noHeadHandle)(char*);
} BG35_Instruction;

typedef struct
{
  char data[300];
  short dataLen;
} BG35_UdpData;

BOOL isRSP = TRUE;              //收到回应标记位，该标记位true时才可以发送下一条AT指令
BOOL baseStationConnectionState = FALSE;//与基站的连接状态

unsigned short interval_isRSP_timeout=2000;//NB模组回应超时时间，若超过该时间还未收到回应，则将isRSP置为TRUE
unsigned short remainTime_isRSP_timeout=2000;//剩余NB模组回应超时时间

BOOL readyRead = FALSE;         //readyRead标记位，当该标记位为true时将优先发送读取数据的AT指令
char readyRead_instruction[20]; //readyRead指令，用于缓存读取数据的AT指令

const char COMMA[] = ",";              //逗号分隔符
char SOCKETID[] = "0";                 //记录BG35的socketID
char SERVER_HOST[] = "112.124.23.170"; //服务器IP
char SERVER_PORT[] = "9000";           //服务器端口

void (*handleOk)() = NULL;          //OK反馈处理函数指针
void (*handleError)() = NULL;       //ERROR反馈处理函数指针
void (*noHeadHandle)(char*) = NULL; //无头反馈处理函数指针

BG35_Instruction lastInstruction; //记录上一条发送的AT指令，一般用于出现错误时的重发

BG35_UdpData BG35_udpDataBuffer[16];                     //接收数据缓冲区，结构为循环队列，为上层模块服务，
unsigned char BG35_udpDataBuffer_begin = 0;                  //接收数据缓冲区开始坐标
unsigned char BG35_udpDataBuffer_end = 0;                    ////接收数据缓冲区结束坐标
unsigned char BG35_udpDataBuffer_mask = 0xf;                 //接收数据缓冲区掩码
BG35_Instruction BG35_sendQueue[16];                          //AT指令发送队列，结构为循环队列，掩码为0xf
unsigned char BG35_sendQueue_begin = 0;                       //发送队列的开始坐标，指向将要发送的指令
unsigned char BG35_sendQueue_end = 0;                         //发送队列的结束坐标，指向最新的指令的后一位
unsigned char BG35_sendQueue_mask = 0xf;                      //发送队列掩码
unsigned char BG35_Uart1_Buffer[1024];                                 //串口接收缓冲区，结构为循环队列，掩码为0xfff
unsigned short BG35_Uart1_Buffer_begin = 0;                   //串口接收缓冲区头部坐标，代表开始解析的位置
unsigned short BG35_Uart1_Buffer_nowAt = 0;                   //串口接收缓冲区当前解析位置，用于避免重复解析
unsigned short BG35_Uart1_Buffer_end = 0;                     //串口接收缓冲区尾部坐标，代表收到的最新数据的后一位
unsigned short BG35_Uart1_Buffer_mask = 0x3ff;                //串口接收缓冲区掩码
USART_TypeDef *serialPortNum = USART1;

BOOL BG35_isRSP() //判断是否可以发送AT指令
{
  return isRSP;
}

BOOL BG35_isSerialPortBufferEmpty() //判断串口缓冲区是否为空
{
  return BG35_Uart1_Buffer_end != BG35_Uart1_Buffer_begin ? FALSE : TRUE;
}

void BG35_appendToUdpDataBuffer(const char data[], short dataLen) //添加UDP数据到UDP数据缓冲区
{
  //初始化要填入数据的数据缓冲区
  memset(BG35_udpDataBuffer[BG35_udpDataBuffer_end].data, 0, sizeof(BG35_udpDataBuffer[BG35_udpDataBuffer_end].data));
  tool_byteArray_copy(BG35_udpDataBuffer[BG35_udpDataBuffer_end].data, data, dataLen); //复制数据到数据缓冲区
  BG35_udpDataBuffer[BG35_udpDataBuffer_end].dataLen = dataLen;                        //复制数据长度
  BG35_udpDataBuffer_end = (BG35_udpDataBuffer_end + 1) & BG35_udpDataBuffer_mask;             //数据缓冲区大小加一
}

void Bg35_removeFirstOfUdpDataBuffer() //从UDP数据缓冲区移除UDP数据
{
  //初始化要移除的数据缓冲区
  memset(BG35_udpDataBuffer[BG35_udpDataBuffer_begin].data, 0, sizeof(BG35_udpDataBuffer[BG35_udpDataBuffer_begin].data));
  BG35_udpDataBuffer_begin = (BG35_udpDataBuffer_begin + 1) & BG35_udpDataBuffer_mask; //数据缓冲区大小减一
}

unsigned short BG35_getSerialPortBufferSize() //得到串口数据缓冲区大小
{
  return (BG35_Uart1_Buffer_end - BG35_Uart1_Buffer_begin) & BG35_Uart1_Buffer_mask;
}

unsigned short BG35_getDataFromUdpDataBuffer(char data[], unsigned short *dataSize)
{
  if (BG35_udpDataBuffer_begin != BG35_udpDataBuffer_end) //若UDP数据缓冲区不为空则执行
    {
      tool_byteArray_copy(data, BG35_udpDataBuffer[BG35_udpDataBuffer_begin].data, BG35_udpDataBuffer[BG35_udpDataBuffer_begin].dataLen);
      *dataSize = BG35_udpDataBuffer[BG35_udpDataBuffer_begin].dataLen;
      Bg35_removeFirstOfUdpDataBuffer(); //删除当前条数据缓冲
      return *dataSize;
    }
  else
    {
      return 0;
    }
}

void BG35_dataBufferGetData(const unsigned short len, char *tarByteArr) //从串口数据缓冲区读数据
{
  unsigned short i = 0;
  for (i = 0; i < len; ++i)
    {
      tarByteArr[i] = BG35_Uart1_Buffer[(BG35_Uart1_Buffer_begin + i) & BG35_Uart1_Buffer_mask];
    }
}

void BG35_dataBufferDropData(const unsigned short len) //串口数据缓冲区丢弃数据
{
  if (0 == len)
    {
      return;
    }
  if (BG35_getSerialPortBufferSize() < len)
    {
      BG35_Uart1_Buffer_begin = BG35_Uart1_Buffer_end = 0;
    }
  else
    {
      BG35_Uart1_Buffer_begin = (BG35_Uart1_Buffer_begin + len) & BG35_Uart1_Buffer_mask;
    }
}

void BG35_dataBufferNowAtMoveToNext(void)
{
  BG35_Uart1_Buffer_nowAt = (BG35_Uart1_Buffer_nowAt+1) & BG35_Uart1_Buffer_mask;
}

void BG35_sendLastInstruction(void) //发送上一条已经发过的指令，因为处理反馈的方式都是一样的，所以直接发送即可
{
  char *data = lastInstruction.instruction;
  while (*data)
    {
      while (USART_GetFlagStatus(serialPortNum, USART_FLAG_TC) == RESET)
        ;
      USART_SendData(serialPortNum, *data);
      ++data;
    }
  while (USART_GetFlagStatus(serialPortNum, USART_FLAG_TC) == RESET)
    ;
  USART_SendData(serialPortNum, '\r');
  while (USART_GetFlagStatus(serialPortNum, USART_FLAG_TC) == RESET)
    ;
  USART_SendData(serialPortNum, '\n');
}

void BG35_noHead_NSOCR(char *instructionPtr) //处理创建socket的无头部反馈
{
  strcpy(SOCKETID, instructionPtr);
  if ('1' == SOCKETID[0]) //若socketID等于1，代表NB模组未初始化完成，需要再等等
    {
      BG35_AT_NSOCL();          //关闭socketID
      tool_delay_ms_plus(5000); //等待
      BG35_AT_NSOCR();          //创建socketID
    }
}

void BG35_noHead_NSORF(char *instructionPtr) //读取缓冲区数据
{
  char result_socket[2];                                                  //端口号
  char result_length[4];                                                  //数据长度
  char remaining_length[4];                                               //剩余长度
  unsigned short dataLen = 0;                                             //解析后的二进制数据长度
  memset(remaining_length, 0, sizeof(remaining_length));                  //初始化剩余长度变量
  tool_string_split_index(instructionPtr, COMMA[0], 5, remaining_length); //将剩余长度填入变量
  if (remaining_length[0] != '0')                                         //若剩余长度不为零
    {
      memset(result_socket, 0, sizeof(result_socket));                     //初始化socket变量
      tool_string_split_index(instructionPtr, COMMA[0], 0, result_socket); //将socket填入变量
      BG35_AT_NSORF(result_socket, remaining_length);                      //发送再次读取的命令
    }
  memset(result_length, 0, sizeof(result_length));                      //初始化长度变量
  tool_string_split_index(instructionPtr, COMMA[0], 3, result_length);  //得到数据长度
  tool_string_split_index(instructionPtr, COMMA[0], 4, instructionPtr); //得到源数据
  tool_string_strToNum(result_length, &dataLen);                        //数据长度格式转换，先得到二进制数据长度
  instructionPtr[2 * dataLen] = 0;                                      //字符格式的数据长度是二进制数据格式长度的二倍，将该位置置零表示字符串的结束
  tool_string_hexStrToByteArr(instructionPtr, instructionPtr);          //源数据格式转换
  BG35_appendToUdpDataBuffer(instructionPtr, dataLen);                  //将解析好的数据存入UDP数据缓冲区
}

void BG35_CEREG(char *instructionPtr)
{
  const unsigned char instructionLen = 7;//"+CEREG:"的字符串长度
  //  char result_EPS_type[2];
  char result_EPS_state[2];
  //  memset(result_EPS_type,0,sizeof (result_EPS_type));
  memset(result_EPS_state,0,sizeof (result_EPS_state));
  //  tool_string_split_index(instructionPtr + instructionLen, COMMA[0],0,result_EPS_type);
  tool_string_split_index(instructionPtr + instructionLen, COMMA[0],1,result_EPS_state);
  if('1'==result_EPS_state[0])
    {
      baseStationConnectionState=TRUE;
    }
  else
    {
      baseStationConnectionState=FALSE;
    }
}

void BG35_NSONMI(char *instructionPtr) //有新消息
{
  const unsigned char instructionLen = 8; //"+NSONMI:"的字符串长度
  char socket[2];                         //socketID字符串
  char dataLen[5];                        //数据长度字符串
  memset(socket, 0, sizeof(socket));
  memset(dataLen, 0, sizeof(dataLen));                                            //从串口数据缓冲区得到数据
  tool_string_split_index(instructionPtr + instructionLen, COMMA[0], 0, socket);  //分离socketID
  tool_string_split_index(instructionPtr + instructionLen, COMMA[0], 1, dataLen); //分离数据长度
  BG35_AT_NSORF(socket, dataLen);                                                 //发送读取数据的AT指令
}

BOOL BG35_waitForBaseStationConnect(const unsigned short maxWaitTime_ms)//等待基站连接，若maxWaitTime_ms=0则代表无限等待
{
  unsigned short totalWaitTime = 0;//总等待时间
  unsigned short waitBaseStationConnect = 0;//等待基站连接重发计时器
  while (!baseStationConnectionState) //当基站尚未连接时，首先连接基站
    {
      if(0!=maxWaitTime_ms)
        {
          //如果启用最大等待时间
          if(totalWaitTime>=maxWaitTime_ms)
            {
              //如果总等待时间超时，则返回失败
              return FALSE;
            }
          ++totalWaitTime;
        }
      if(0==waitBaseStationConnect)
        {
          //如果等待连接计时器等于0，则需要新的查询
          waitBaseStationConnect=5*1000;
          BG35_AT_CEREG();//查询当前基站连接状态
        }
      BG35_sendData_queue(); //尝试发送数据
      BG35_decode();//解析
      waitBaseStationConnect==0?0:--waitBaseStationConnect;//计时器自减一至零
      delay_ms(1);//延时1ms
    }
  return TRUE;//若基站已连接，则会跳出循环，返回成功
}

BOOL BG35_waitForOpenSocket(const unsigned short maxWaitTime_ms) //等待socket打开，若maxWaitTime_ms=0则代表无限等待
{
  unsigned short totalWaitTime = 0; //延时时间计数器
  while ('0' == SOCKETID[0]) //若socketID为0，代表socket还未打开
    {
      if(0!=maxWaitTime_ms)
        {
          //如果启用最大等待时间
          if (maxWaitTime_ms <= totalWaitTime) //若超出最大等待时间
            {
              return FALSE; //若socketID不等于0则代表打开成功
            }
          ++totalWaitTime;
        }
      BG35_sendData_queue(); //尝试发送数据
      BG35_decode();         //尝试解析数据
      delay_ms(1);
    }
  return TRUE;
}

BOOL BG35_isUdpDataBufferEmpty() //判断UDP数据缓冲区是否为空
{
  return BG35_udpDataBuffer_begin != BG35_udpDataBuffer_end ? FALSE : TRUE;
}

BOOL BG35_judgeInstruction(const char *instruction) //现有的数据头部是否符合
{
  const unsigned short len = strlen(instruction);
  char temp[600];
  memset(temp, 0, sizeof(temp));
  if (BG35_getSerialPortBufferSize() < len)
    {
      return FALSE;
    }
  BG35_dataBufferGetData(len, temp);
  return tool_string_equal_len(instruction, temp, len) ? TRUE : FALSE;
}

void BG35_appendToSendQueue(const char *data,
                            void (*handleOk)(),
                            void (*handleError)(),
                            void (*noHeadHandle)(char*)) //添加新的指令到发送队列
{
  memset(BG35_sendQueue[BG35_sendQueue_end].instruction, 0, sizeof(BG35_sendQueue[BG35_sendQueue_end].instruction)); //初始化发送队列的末尾
  strcpy(BG35_sendQueue[BG35_sendQueue_end].instruction, data);                                            //拼装新指令
  BG35_sendQueue[BG35_sendQueue_end].handleOk = handleOk;
  BG35_sendQueue[BG35_sendQueue_end].handleError = handleError;
  BG35_sendQueue[BG35_sendQueue_end].noHeadHandle = noHeadHandle;
  BG35_sendQueue_end = (BG35_sendQueue_end + 1) & BG35_sendQueue_mask; //数据发送队列队尾自增一
  BG35_sendData_queue();                                //发送队列尝试发送数据
}

void BG35_sendData_queue() //发送队列尝试发送数据
{
  char *sendPtr = NULL; //发送指针
  if(0==remainTime_isRSP_timeout)
    {
      isRSP=TRUE;
      remainTime_isRSP_timeout=interval_isRSP_timeout;
    }
  if (!isRSP)           //若没有收到OK或ERROR回应则不应发送
    {
      return;
    }
  if (readyRead) //有新的消息应当先读
    {
      readyRead = FALSE;                                                           //将可以读取标记位置为FALSE，代表不可读
      isRSP = FALSE;                                                               //将回应标记位置为FALSE，代表未得到回应
      memset(lastInstruction.instruction, 0, sizeof(lastInstruction.instruction)); //初始化上一条发送指令
      strcpy(lastInstruction.instruction, readyRead_instruction);                  //复制读取指令到上一条发送指令
      lastInstruction.handleError = NULL;                                          //使用NSORF专用的处理ERROR函数
      lastInstruction.noHeadHandle = BG35_noHead_NSORF;                            //使用NSORF专用的处理noHead函数
      sendPtr = lastInstruction.instruction;                                       //将发射指针指向要发送的数据的第一个字节
      handleOk = NULL;                                                             //处理OK函数置为空
      handleError = BG35_sendLastInstruction;                                      //处理ERROR函数指向NSORF的ERROR处理函数
      noHeadHandle = lastInstruction.noHeadHandle;                                 //处理无头函数指向NSORF的无头处理函数
    }
  else if (BG35_sendQueue_end != BG35_sendQueue_begin) //没有新消息且发送队列不为空
    {
      isRSP = FALSE;                                                               //将回应标记位置为FALSE，代表未得到回应
      memset(lastInstruction.instruction, 0, sizeof(lastInstruction.instruction)); //初始化上一条发送指令
      strcpy(lastInstruction.instruction, BG35_sendQueue[BG35_sendQueue_begin].instruction); //复制当前队列中的指令到上一条发送指令
      lastInstruction.handleOk = BG35_sendQueue[BG35_sendQueue_begin].handleOk;              //使用当前指令的OK处理函数
      lastInstruction.handleError = BG35_sendQueue[BG35_sendQueue_begin].handleError;        //使用当前指令的ERROR处理函数
      lastInstruction.noHeadHandle = BG35_sendQueue[BG35_sendQueue_begin].noHeadHandle;      //使用当前指令的无头处理函数
      BG35_sendQueue_begin = (BG35_sendQueue_begin + 1) & BG35_sendQueue_mask;                    //发送队列开始标记自增一
      sendPtr = lastInstruction.instruction;                                       //将发射指针指向要发送的数据的第一个字节
      handleOk = lastInstruction.handleOk;                                         //填入OK处理函数
      handleError = lastInstruction.handleError;                                   //填入error处理函数
      noHeadHandle = lastInstruction.noHeadHandle;
    }
  if (NULL == sendPtr) //如果发送指针为空则直接返回
    {
      return;
    }
  while (*sendPtr)
    {
      while (USART_GetFlagStatus(serialPortNum, USART_FLAG_TC) == RESET)
        ;
      USART_SendData(serialPortNum, *sendPtr);
      ++sendPtr;
    }
  while (USART_GetFlagStatus(serialPortNum, USART_FLAG_TC) == RESET)
    ;
  USART_SendData(serialPortNum, '\r');
  while (USART_GetFlagStatus(serialPortNum, USART_FLAG_TC) == RESET)
    ;
  USART_SendData(serialPortNum, '\n');
}

//对接收的串口数据进行处理
void BG35_decode()
{
  // char OK[] = "OK";
  // char ERROR[] = "ERROR";
  // char NSONMI[] = "+NSONMI:";
  char temp[600]; //用于临时存放准备解析的数据
  //  unsigned short bufferSize = 0;
  while (BG35_Uart1_Buffer_nowAt != BG35_Uart1_Buffer_end) //如果当前解析位置不等于串口缓冲区结束位置，则开始解析
    {
      if (BG35_Uart1_Buffer_nowAt == BG35_Uart1_Buffer_begin) //如果当前解析位置与串口数据缓冲区开始位置相等
        {
          if ('\r' == BG35_Uart1_Buffer[BG35_Uart1_Buffer_begin] ||
              '\n' == BG35_Uart1_Buffer[BG35_Uart1_Buffer_begin]) //如果串口缓冲区的开始是字符'\r'或'\n'时直接丢弃
            {
              BG35_dataBufferDropData(1);              //串口缓冲区丢弃1字节数据
              BG35_Uart1_Buffer_nowAt = BG35_Uart1_Buffer_begin; //当前解析位置保持与开始位置相等
            }
          else //串口缓冲区开始是其他字符
            {
              BG35_dataBufferNowAtMoveToNext(); //解析位置移动到下一个字节
            }
        }
      else //如果当前解析位置与串口数据缓冲区开始位置不相等
        {
          if ('\r' == BG35_Uart1_Buffer[BG35_Uart1_Buffer_nowAt]) //如果当前解析位置是字符'\r'，则说明得到了完整的指令，开始解析
            {
              memset(temp, 0, sizeof(temp));                                                               //初始化
              BG35_dataBufferGetData((BG35_Uart1_Buffer_nowAt - BG35_Uart1_Buffer_begin) & BG35_Uart1_Buffer_mask, temp); //从缓冲区得到数据
              if ('O' == temp[0])                                                                          //如果第一个字符是'O'，则说明是OK
                {
                  isRSP = TRUE;
                  remainTime_isRSP_timeout=interval_isRSP_timeout;
                  if (NULL != handleOk)
                    {
                      handleOk();
                    }
                  else
                    {
                      BG35_sendData_queue();
                    }
                }
              else if ('E' == temp[0]) //如果第一个字符是'E，则代表是ERROR
                {
                  isRSP = TRUE;
                  remainTime_isRSP_timeout=interval_isRSP_timeout;
                  if (NULL != handleError)
                    {
                      handleError();
                    }
                  else
                    {
                      BG35_sendData_queue();
                    }
                }
              else if ('+' == temp[0]) //如果第一个字符是'+'，则代表是+NSONMI:
                {
                  if('N' == temp[1])
                    {
                      BG35_NSONMI(temp);
                    }
                  else if('C' == temp[1])
                    {
                      BG35_CEREG(temp);
                    }
                }
              else if (noHeadHandle) //否则可能是无头部反馈，如果无头部反馈指针不为空则说明可以处理
                {
                  noHeadHandle(temp);
                }
              BG35_Uart1_Buffer_begin = BG35_Uart1_Buffer_nowAt; //解析完毕后开始位置与当前解析位置保持一致
            }
          else //如果是其他字符
            {
              BG35_dataBufferNowAtMoveToNext(); //解析位置移动到下一个字节
            }
        }
    }
}

//中断接收函数
void USART1_IRQHandler(void) //串口1中断服务程序， 不做处理直接上报
{
  if (USART_GetITStatus(serialPortNum, USART_IT_RXNE) != RESET)
    {
      BG35_Uart1_Buffer[BG35_Uart1_Buffer_end] = USART_ReceiveData(USART1);
      BG35_Uart1_Buffer_end = (BG35_Uart1_Buffer_end + 1) & BG35_Uart1_Buffer_mask;
    }
}

//初始化NB模块
void BG35_init()
{
  unsigned short temp = 0;
  memset(BG35_Uart1_Buffer, 0, sizeof(BG35_Uart1_Buffer));
  for (temp = 0; temp < 16; ++temp)
    {
      memset(BG35_udpDataBuffer[temp].data, 0, sizeof(BG35_udpDataBuffer[temp].data));
      BG35_udpDataBuffer[temp].dataLen = 0;
      memset(BG35_sendQueue[temp].instruction, 0, sizeof(BG35_sendQueue[temp].instruction));
      BG35_sendQueue[temp].noHeadHandle = NULL;
    }
  tool_delay_ms_plus(10000);
}

void BG35_AT()
{
  char AT[] = "AT";
  BG35_appendToSendQueue(AT, NULL, NULL, NULL);
  BG35_sendData_queue();
}

void BG35_AT_NSOCR()
{
  char AT_NSOCR[40] = "AT+NSOCR=DGRAM,17,8000,1,AF_INET";
  BG35_appendToSendQueue(AT_NSOCR, NULL, NULL, BG35_noHead_NSOCR);
  BG35_sendData_queue();
}

void BG35_AT_NSOCL()
{
  char AT_NSOCL[15] = "AT+NSOCL=";
  if ('0' == SOCKETID[0])
    {
      return;
    }
  AT_NSOCL[9] = SOCKETID[0];
  SOCKETID[0] = '0';
  BG35_appendToSendQueue(AT_NSOCL, NULL, BG35_sendLastInstruction, NULL);
  BG35_sendData_queue();
}

void BG35_AT_NSOST(const char *data, const unsigned short dataLen)
{
  const char AT_NSOST[] = "AT+NSOST=";
  char len[5];
  //AT+NSOST=<socket>,<remote_addr>,<remote_port>,<length>,<data>[,<sequence>]
  char temp[600];
  if ('0' == SOCKETID[0])
    {
      return;
    }
  memset(temp, 0, sizeof(temp));
  memset(len, 0, 5);
  tool_string_numToStr(dataLen, len);
  strcat(temp, AT_NSOST);
  strcat(temp, SOCKETID);
  strcat(temp, COMMA);
  strcat(temp, SERVER_HOST);
  strcat(temp, COMMA);
  strcat(temp, SERVER_PORT);
  strcat(temp, COMMA);
  strcat(temp, len);
  strcat(temp, COMMA);
  tool_string_byteArrToHexStr(data, dataLen, temp + strlen(temp));
  BG35_appendToSendQueue(temp, NULL, BG35_sendLastInstruction, NULL);
  BG35_sendData_queue();
}

void BG35_AT_NSORF(const char *socketID, const char *len)
{
  const char AT_NSORF[] = "AT+NSORF=";
  //AT+NSORF=<socket>,<req_length>
  memset(readyRead_instruction, 0, sizeof(readyRead_instruction)); //初始化读取指令的缓冲区
  strcat(readyRead_instruction, AT_NSORF);                         //复制AT指令头部
  if (NULL == socketID)                                            //若输入的socketID为空，则使用已开启的socketID
    {
      if ('0' != SOCKETID[0]) //若已开启的socketID为0，则代表尚未开启socket
        {
          strcat(readyRead_instruction, SOCKETID); //填入当前已开启的socketID
        }
      else
        {
          return;
        }
    }
  else //若输入的socketID不为空，则使用输入的socketID
    {
      strcat(readyRead_instruction, socketID);
    }
  strcat(readyRead_instruction, COMMA); //添加逗号分隔符
  if (NULL == len)                      //若输入的读取长度为空，则使用默认读取长度
    {
      strcat(readyRead_instruction, "300");
    }
  else if ('0' != len[0]) //若输入的读取长度不为0，则填入读取长度
    {
      strcat(readyRead_instruction, len);
    }
  else //若输入的读取长度为0，则放弃发送
    {
      return;
    }
  //和上位机不一样，添加紧急发送到发送队列的行为存在危险，因此使用额外的标志位
  readyRead = TRUE; //将readyRead标记位置为TRUE
  BG35_sendData_queue();
}

void BG35_AT_CEREG(void)
{
  const char AT_CEREG[] = "AT+CEREG?";
  char temp[600];
  memset(temp, 0, sizeof(temp));
  strcat(temp, AT_CEREG);
  BG35_appendToSendQueue(temp, NULL, BG35_sendLastInstruction, NULL);
  BG35_sendData_queue();
}
